package com.frogs.ucenter.v1.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.frogs.framework.util.PageList;
import com.frogs.framework.util.StringUtil;
import com.frogs.system.util.ApplicablePlatformEnum;
import com.frogs.system.util.ExpandCodeEnum;
import com.frogs.system.util.RechargeBalanceStatusEnum;
import com.frogs.system.util.RechargeIntegralEnum;
import com.frogs.system.util.RechargeStragetyEnum;
import com.frogs.system.util.UserIntegralRecordEnum;
import com.frogs.system.web.exception.ServiceOperationException;
import com.frogs.ucenter.dao.UserIntegralBalanceDao;
import com.frogs.ucenter.dao.UserIntegralRecordDao;
import com.frogs.ucenter.dao.UserRechargeBalanceDao;
import com.frogs.ucenter.dao.UserRechargeConsumeBlockingDao;
import com.frogs.ucenter.dao.UserRechargeGiveMoneyDao;
import com.frogs.ucenter.dao.UserRechargeStrategyChooseDao;
import com.frogs.ucenter.dao.UserRechargeStrategyDao;
import com.frogs.ucenter.entity.UserIntegralBalance;
import com.frogs.ucenter.entity.UserIntegralRecord;
import com.frogs.ucenter.entity.UserRechargeBalance;
import com.frogs.ucenter.entity.UserRechargeConsumeBlocking;
import com.frogs.ucenter.entity.UserRechargeGiveMoney;
import com.frogs.ucenter.entity.UserRechargeStrategyChoose;
import com.frogs.ucenter.util.Constants;

public class UserRechargeStrategyBaseServiceImpl{
	private static final Logger log = LoggerFactory.getLogger(UserRechargeStrategyBaseServiceImpl.class);
	@Resource
	private UserRechargeStrategyChooseDao userRechargeStrategyChooseDao;
	@Resource
	private UserRechargeStrategyDao userRechargeStrategyDao;
	@Resource
	private UserRechargeGiveMoneyDao userRechargeGiveMoneyDao;
	@Resource
	protected UserIntegralRecordDao userIntegralRecordDao;
	@Resource
	private UserIntegralBalanceDao userIntegralBalanceDao;
	@Resource
	private UserRechargeConsumeBlockingDao blockingDao;
	@Resource
	private UserRechargeBalanceDao userRechargeBalanceDao;
	/**
	 * 根据类型获取策略
	 * @param type 策略类型,1表示充值策略,2表示积分策略
	 * @param applicablePlatformId 平台
	 * @param expandCode 渠道
	 * @return 子策略ID
	 */
	protected int getRechargeStrategy(Integer type, Integer applicablePlatformId, String expandCode) throws Exception {
		int subId = 0;
		if(StringUtil.isEmpty(expandCode)){
			expandCode = ExpandCodeEnum.MALL.getId();
		}
		if(StringUtil.isEmpty(applicablePlatformId)){
			applicablePlatformId = ApplicablePlatformEnum.WEB.getId();
		}
		try {//1表示充值策略,2表示积分策略
			Map<String, Object> params = new HashMap<String, Object>();
			params.put("eqTypeId", type);
			params.put("eqApplicablePlatformId", applicablePlatformId);
			params.put("eqExpandCode", expandCode);
			PageList<UserRechargeStrategyChoose> list = userRechargeStrategyChooseDao.selectByMap(params, false);
			UserRechargeStrategyChoose userRechargeStrategyChoose = new UserRechargeStrategyChoose();
			if(list.size() > 0){
				userRechargeStrategyChoose = list.get(0);
			}else{
				return subId;
			}
			subId = userRechargeStrategyChoose.getSubId();
		} catch (Exception e) {
			log.error("func[getRechargeStrategy] type [" + type + "] error[" + e.getMessage() + "]", e);
			throw new ServiceOperationException("请求处理失败：" + e.getMessage());
		}
		return subId;
	}

	/**
	 * 根据子策略和充值金额获取赠送的金额
	 * @param subId 子策略ID
	 * @param rechargeNum 充值金额
	 * @return 赠送的金额
	 */
	protected BigDecimal getGiveMoney(Integer subId,BigDecimal rechargeNum) throws Exception {
		BigDecimal giveNum = new BigDecimal("0.00");
		try {
			Map<String, Object> params = new HashMap<String, Object>();
			params.put("type", RechargeIntegralEnum.RECHARGE.getId());
			params.put("subId", subId);
			if(1 == subId){//根据数值或者赠送金额
				List<Map<String, Object>> list = userRechargeStrategyDao.selectNumTypeByMap(params);
				if(null == list){
					return giveNum;
				}
				for(Map<String,Object> map:list){
					if (StringUtil.isEmpty(map.get("rc_money")) || StringUtil.isEmpty(map.get("give_money")) || 
							Float.parseFloat(map.get("rc_money").toString()) == 0 || Float.parseFloat(map.get("give_money").toString()) == 0)
						continue;
					giveNum = giveNum.add(BigDecimal.valueOf((int)Math.floor((rechargeNum.doubleValue()/Float.parseFloat(map.get("rc_money").toString())))*Float.parseFloat(map.get("give_money").toString())));
					rechargeNum = rechargeNum.subtract(BigDecimal.valueOf((int)Math.floor(rechargeNum.doubleValue()/Float.parseFloat(map.get("rc_money").toString()))*Float.parseFloat(map.get("rc_money").toString())));
				}
			}else if(2 == subId){//根据比例获取赠送金额
				List<Map<String, Object>> list = userRechargeStrategyDao.selectRatioTypeByMap(params);
				if(null == list){
					return giveNum;
				}
				for(Map<String,Object> map:list){
					giveNum = giveNum.add(BigDecimal.valueOf(rechargeNum.floatValue()*Float.parseFloat(map.get("ratio").toString())));
				}
			}
		} catch (Exception e) {
			log.error("func[giveMoney] subId [" + subId + "] rechargeNum [" + rechargeNum + "] error[" + e.getMessage() + "]", e);
			throw new ServiceOperationException("请求处理失败：" + e.getMessage());
		}
		return giveNum.setScale(2, BigDecimal.ROUND_HALF_UP);
	}
	
	/**
	 * 根据子策略和充值金额获取赠送的积分
	 * @param subId 子策略ID
	 * @param rechargeNum 充值金额
	 * @return 赠送的积分
	 */
	protected BigDecimal getGiveIntegral(Integer subId,BigDecimal rechargeNum) throws Exception {
		BigDecimal giveNum = new BigDecimal("0.00");
		try {
			Map<String, Object> params = new HashMap<String, Object>();
			params.put("type", RechargeIntegralEnum.RECHARGE.getId());
			params.put("subId", subId);
			params.put("expandCode", ExpandCodeEnum.MALL.getId());
			params.put("applicablePlatformId", ApplicablePlatformEnum.WEB.getId());
			if(1 == subId){//根据数值或者赠送金额
				List<Map<String, Object>> list = userRechargeStrategyDao.selectNumTypePointByMap(params);
				if(null == list){
					return giveNum;
				}
				for(Map<String,Object> map:list){
					if (StringUtil.isEmpty(map.get("rc_money")) || StringUtil.isEmpty(map.get("give_point")) || 
							Float.parseFloat(map.get("rc_money").toString()) == 0 || Float.parseFloat(map.get("give_point").toString()) == 0)
						continue;
					giveNum = giveNum.add(BigDecimal.valueOf((int)Math.floor((rechargeNum.doubleValue()/Float.parseFloat(map.get("rc_money").toString())))*Float.parseFloat(map.get("give_point").toString())));
					rechargeNum = rechargeNum.subtract(BigDecimal.valueOf((int)Math.floor(rechargeNum.doubleValue()/Float.parseFloat(map.get("rc_money").toString()))*Float.parseFloat(map.get("rc_money").toString())));
				}
			}else if(2 == subId){//根据比例获取赠送金额
				List<Map<String, Object>> list = userRechargeStrategyDao.selectRatioTypePointByMap(params);
				if(null == list){
					return giveNum;
				}
				for(Map<String,Object> map:list){
					giveNum = giveNum.add(BigDecimal.valueOf(rechargeNum.floatValue()*Float.parseFloat(map.get("ratio").toString())));
				}
			}
		} catch (Exception e) {
			log.error("func[getGiveIntegral] subId [" + subId + "] rechargeNum [" + rechargeNum + "] error[" + e.getMessage() + "]", e);
			throw new ServiceOperationException("请求处理失败：" + e.getMessage());
		}
		return giveNum.setScale(2, BigDecimal.ROUND_HALF_UP);
	}


	/**
	 * 根据子策略和消费金额获取赠送的积分
	 * @param subId 子策略ID
	 * @param consumeNum 消费金额
	 * @return 消费获得的赠送积分
	 */
	protected int getGivePoint(Integer subId, BigDecimal consumeNum, Integer applicablePlatformId, String expandCode) throws Exception {
		float giveNum = 0;
		try {
			Map<String, Object> params = new HashMap<String, Object>();
			params.put("type", RechargeIntegralEnum.INTEGRAL.getId());
			params.put("subId", subId);
			params.put("expandCode", expandCode);
			params.put("applicablePlatformId", applicablePlatformId);
			if(1 == subId){//根据数值或者赠送积分
				List<Map<String, Object>> list = userRechargeStrategyDao.selectNumTypePointByMap(params);
				if(null == list){
					return (int)Math.floor(giveNum);
				}
				for(Map<String,Object> map:list){
					giveNum = giveNum + (int)Math.floor((consumeNum.doubleValue()/Float.parseFloat(map.get("rc_money").toString())))*Float.parseFloat(map.get("give_point").toString());
					consumeNum = consumeNum.subtract(BigDecimal.valueOf((int)Math.floor(consumeNum.doubleValue()/Float.parseFloat(map.get("rc_money").toString()))*Float.parseFloat(map.get("rc_money").toString())));
				}
			}else if(2 == subId){//根据比例获取赠送积分
				List<Map<String, Object>> list = userRechargeStrategyDao.selectRatioTypePointByMap(params);
				if(null == list){
					return (int)Math.floor(giveNum);
				}
				for(Map<String,Object> map:list){
					giveNum = giveNum + (int)Math.floor(consumeNum.floatValue()*Float.parseFloat(map.get("ratio").toString()));
				}
			}
		} catch (Exception e) {
			log.error("func[givePoint] subId [" + subId + "] consumeNum [" + consumeNum + "] error[" + e.getMessage() + "]", e);
			throw new ServiceOperationException("请求处理失败：" + e.getMessage());
		}
		return (int)Math.floor(giveNum);
	}
	
	/**
	 * 根据充值金额和充值id登记赠送金额,提供外部调用
	 * @param rechargeMoney 充值金额
	 * @param rechargeId 充值id
	 * @return 赠送金额
	 */
	protected BigDecimal giveMoney(BigDecimal rechargeMoney ,Integer rechargeId) throws Exception {
		BigDecimal giveNum = null;
		BigDecimal b = new BigDecimal(0);
		int subId = getRechargeStrategy(RechargeIntegralEnum.RECHARGE.getId(), ApplicablePlatformEnum.WEB.getId(), ExpandCodeEnum.MALL.getId());
		String remark = "";
		if(0 == subId){//subId等于0,表示没有充值策略,不进行充值赠送
			giveNum = new BigDecimal(0);
		}else{//subId等于1,表示按数值赠送,2表示按比例赠送
			if(1 == subId){
				remark = RechargeStragetyEnum.RECHARGEBYNUM.getName();
			}else if(2 == subId){
				remark = RechargeStragetyEnum.RECHARGEBYRATIO.getName();
			}
			giveNum = getGiveMoney(subId ,rechargeMoney );
			if(giveNum.compareTo(b)>=1){//赠送金额大于0,进行赠送金额登记
				UserRechargeGiveMoney userRechargeGiveMoney = new UserRechargeGiveMoney();
				userRechargeGiveMoney.setGiveMoney(giveNum);
				userRechargeGiveMoney.setRemark(remark);
				userRechargeGiveMoney.setRechargeId(rechargeId);
				userRechargeGiveMoneyDao.insert(userRechargeGiveMoney);
			}
		}
		return giveNum;
	}
	
	/**
	 * 根据充值金额和充值id登记赠送积分
	 * @param rechargeMoney 充值金额
	 * @param rechargeId 充值id
	 * @return 赠送积分
	 */
	protected BigDecimal giveIntegral(BigDecimal rechargeMoney ,Integer rechargeId, Integer userId) throws Exception {
		BigDecimal giveNum = new BigDecimal("0.00");
		BigDecimal b = new BigDecimal(0);
		int subId = getRechargeStrategy(RechargeIntegralEnum.RECHARGE.getId(), ApplicablePlatformEnum.WEB.getId(), ExpandCodeEnum.MALL.getId());
		String remark = "";
		if(0 == subId){//subId等于0,表示没有充值策略,不进行充值赠送
			giveNum = new BigDecimal("0.00");
		}else{//subId等于1,表示按数值赠送,2表示按比例赠送
			if(1 == subId){
				remark = RechargeStragetyEnum.RECHARGEBYNUM.getName();
			}else if(2 == subId){
				remark = RechargeStragetyEnum.RECHARGEBYRATIO.getName();
			}
			giveNum = getGiveIntegral(subId ,rechargeMoney );
			if(giveNum.compareTo(b)>=1){//赠送金额大于0,进行赠送金额登记
				UserIntegralRecord userIntegralRecord = new UserIntegralRecord();
				userIntegralRecord.setIntegralNum(giveNum.intValue());
				userIntegralRecord.setIntegralTime(new Date());
				userIntegralRecord.setRemark(remark);
				userIntegralRecord.setExpandCode("");
				userIntegralRecord.setApplicablePlatformId(ApplicablePlatformEnum.WEB.getId());
				userIntegralRecord.setType(UserIntegralRecordEnum.RECHARGE_MONEY.getId());
				userIntegralRecord.setUserId(userId);
				userIntegralRecord.setOrderId(rechargeId.toString());
				userIntegralRecordDao.insert(userIntegralRecord);
			}
		}
		return giveNum;
	}

	/**
	 * 根据用户id、消费金额、积分来源登记积分
	 * @param userId 用户ID
	 * @param consumeNum 消费金额
	 * @param type 积分来源
	 */
	protected void givePointByConsume(Integer userId, BigDecimal consumeNum, Integer type, String expandCode, String remark, int applicablePlatformId, String orderId) throws Exception {
		int giveNum = 0;
		int subId = getRechargeStrategy(RechargeIntegralEnum.INTEGRAL.getId(), applicablePlatformId, expandCode);
		if(0 == subId){//subId等于0,表示没有积分赠送策略,不进行消费积分赠送
			
		}else{//subId等于1,表示按数值赠送,2表示按比例赠送
			giveNum = getGivePoint(subId ,consumeNum, applicablePlatformId, expandCode );
			if(giveNum>0){
				givePoint(userId ,giveNum ,type ,expandCode, remark, applicablePlatformId, orderId);
			}
		}
	}


	/**
	 * 根据用户id、积分数量、积分来源登记积分
	 * @param userId 用户ID
	 * @param integralNum 积分数量
	 * @param type 积分来源
	 */
	protected void givePoint(Integer userId, Integer integralNum, Integer type, String expandCode, String remark, Integer applicablePlatformId, String orderId) {
		UserIntegralRecord userIntegralRecord = new UserIntegralRecord();
		userIntegralRecord.setIntegralNum(integralNum);
		userIntegralRecord.setType(type);
		userIntegralRecord.setUserId(userId);
		userIntegralRecord.setExpandCode(expandCode);
		userIntegralRecord.setRemark(remark);
		userIntegralRecord.setApplicablePlatformId(applicablePlatformId);
		userIntegralRecord.setOrderId(orderId);
		userIntegralRecordDao.insert(userIntegralRecord);
		
		UserIntegralBalance userIntegralBalance = userIntegralBalanceDao.selectById(userId);
		if(null == userIntegralBalance){//不存在则进行插入操作
			userIntegralBalance = new UserIntegralBalance();
			userIntegralBalance.setIntegralUsable(integralNum);
			userIntegralBalance.setIntegralUsed(0);
			userIntegralBalance.setId(userId);
			userIntegralBalanceDao.insert(userIntegralBalance);
		}else{//存在则进行更新操作
			int integralUsable = userIntegralBalance.getIntegralUsable();
			userIntegralBalance = new UserIntegralBalance();
			userIntegralBalance.setId(userId);
			userIntegralBalance.setIntegralUsable(integralUsable + integralNum);
			userIntegralBalanceDao.update(userIntegralBalance);
		}
	}
	
	/**
	 * 获取订单冻结金额
	 * @param orderId
	 * @return
	 */
	protected BigDecimal showBlockingMoney(String orderId) {
		Map<String,Object> params = new HashMap<String,Object>();
		params.put("eqStatus", RechargeBalanceStatusEnum.BLOCKING.getId());
		params.put("eqOrderId", orderId);
		List<UserRechargeConsumeBlocking> list = blockingDao.selectByMap(params, false);
		if(null != list && !list.isEmpty()) {
			return list.get(0).getAmount();
		} else {
			return new BigDecimal("0.00");
		}
	}
	
	/**
	 * 更新余额
	 * 
	 * @param rechargeMoney
	 * @param userId
	 */
	protected void rechargeBalance(BigDecimal rechargeMoney, Integer userId) {
		log.info("func[rechargeBalance] rechargeMoney[" + rechargeMoney + "] userId[" + userId + "] desc[update balance before]");
		UserRechargeBalance userRechargeBalance = userRechargeBalanceDao.selectById(userId);
		if (userRechargeBalance != null) {
			BigDecimal balance = userRechargeBalance.getBalance();
			String encryptBalance = userRechargeBalance.getEncryptBalance();
			if (StringUtil.md5(userId + balance.toString(), Constants.ENCRYPT_BALABCE_KEY).equals(encryptBalance)) {
				userRechargeBalance.setBalance(balance.add(rechargeMoney).setScale(2, BigDecimal.ROUND_HALF_UP));
				userRechargeBalance.setEncryptBalance(StringUtil.md5(userId + balance.add(rechargeMoney).setScale(2, BigDecimal.ROUND_HALF_UP).toString(), Constants.ENCRYPT_BALABCE_KEY));
				userRechargeBalance.setUpdateDate(new Date());
				userRechargeBalanceDao.update(userRechargeBalance);
			} else {
				log.error("func[rechargeBalance] userId[" + userId + "] balance[" + balance + "] desc[旧的余额有误]");
			}
		} else {
			userRechargeBalance = new UserRechargeBalance();
			userRechargeBalance.setId(userId);
			userRechargeBalance.setBalance(rechargeMoney);
			userRechargeBalance.setEncryptBalance(StringUtil.md5(userId + rechargeMoney.toString(), Constants.ENCRYPT_BALABCE_KEY));
			userRechargeBalanceDao.insert(userRechargeBalance);
		}
	}
}
